home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / fs / perform.c < prev    next >
C/C++ Source or Header  |  1995-03-21  |  10KB  |  381 lines

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <dos.h>
  4. #include <pc.h>
  5. #include <go32.h>
  6. #include <dpmi.h>
  7. #define far
  8. #include "ed.h"
  9. #include "paging.h"
  10. #include "perform.h"
  11. #include "fsfuncts.h"
  12.  
  13. #define timer_channel 0x40   /* Timer channel (#0) of the timer chip  */
  14. #define command_reg 0x43     /* Command register of the timer chip    */
  15. #define ch_0_seq 0x36        /* 00110110 : ch 0, 2 bytes, mode 3, bin */
  16. #define pulses_per_mili 1193 /* Number of pulses per call to New08()  */
  17. #define calls_per_tick 55    /* 65536/pulses_per_mili=calls per .055s */
  18. #define dos_clock_limit 0x0000fffe /* 65535                           */
  19.  
  20. extern Go32_Info_Block _go32_info_block;
  21.  
  22. typedef struct {
  23.     unsigned short limit;
  24.     unsigned short base_lo;
  25.     unsigned long  base_hi;
  26. } IDT_STRUCT;
  27.  
  28. typedef struct {
  29.     unsigned short offset_lo;
  30.     unsigned short selector;
  31.     unsigned short type;
  32.     unsigned short offset_hi;
  33. } IDT_ENTRY;
  34.  
  35. typedef struct {
  36.     unsigned short segment_limit;
  37.     unsigned short base_00_15;
  38.     unsigned char  base_16_23;
  39.     unsigned char  dummy1;
  40.     unsigned char  dummy2;
  41.     unsigned char  base_24_31;
  42. } GDT_ENTRY;
  43.  
  44. IDT_STRUCT idt, gdt;
  45.  
  46. EVAL_DATA_TABLE evaluation_data;
  47. word32 total_hits_count = 0;
  48. int total_segments = EVAL_SEGMENTS;
  49. int timer_is_set = 0;
  50. int evaluation_is_running = 0;
  51.  
  52. static _go32_dpmi_seginfo   old_rm_isr;
  53. static _go32_dpmi_registers old_isr_regs;
  54. static _go32_dpmi_seginfo   emu_rm_si;
  55. static _go32_dpmi_registers emu_rm_regs;
  56. static _go32_dpmi_seginfo   emu_pm_si;
  57. static _go32_dpmi_seginfo   pm_si;
  58. static IDT_ENTRY  pm_old_idt_entry;
  59. static union REGS regs;
  60.  
  61. volatile word32 dos_clock_tick = 0;
  62. volatile word32 ebp, eip, esp;
  63. static word32 segment_str_addr = 0, segment_stp_addr = 0, segment_len = 1;
  64.  
  65. static int ok_to_run = 0;
  66.  
  67. /* ---------------------------------------------------------------------- */
  68. static void
  69. get_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
  70. {
  71.   unsigned long idt_base, gdt_base;
  72.   int idt_index = vectnum & 0xff;
  73.   IDT_ENTRY *i_e;
  74.  
  75.   asm("movl $_idt,%eax");
  76.   asm("sidt (%eax)");
  77.   asm("movl $_gdt,%eax");
  78.   asm("sgdt (%eax)");
  79.  
  80.   if (idt_index >= 0x08 && idt_index <= 0x0f)
  81.     idt_index += _go32_info_block.master_interrupt_controller_base - 8;
  82.   else if (idt_index >= 0x70 && idt_index <= 0x77)
  83.     idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
  84.  
  85.   idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
  86.   gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
  87.  
  88.   i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
  89.  
  90.   if (i_e->selector > gdt.limit)
  91.     return;
  92.  
  93.   idt_entry->offset_lo = i_e->offset_lo;
  94.   idt_entry->selector  = i_e->selector;
  95.   idt_entry->type      = i_e->type;
  96.   idt_entry->offset_hi = i_e->offset_hi;
  97. }
  98. /* ---------------------------------------------------------------------- */
  99. static void
  100. set_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
  101. {
  102.   unsigned long idt_base, gdt_base;
  103.   int idt_index = vectnum & 0xff;
  104.   IDT_ENTRY *i_e;
  105.  
  106.   asm("movl $_idt,%eax");
  107.   asm("sidt (%eax)");
  108.   asm("movl $_gdt,%eax");
  109.   asm("sgdt (%eax)");
  110.  
  111.   if (idt_index >= 0x08 && idt_index <= 0x0f)
  112.     idt_index += _go32_info_block.master_interrupt_controller_base - 8;
  113.   else if (idt_index >= 0x70 && idt_index <= 0x77)
  114.     idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
  115.  
  116.   idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
  117.   gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
  118.  
  119.   i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
  120.  
  121. /*  if (idt_entry->selector > gdt.limit)
  122.     return;
  123. */   /* Has to comment out because the original selector might not be. */
  124.  
  125.   i_e->offset_lo = idt_entry->offset_lo;
  126.   i_e->selector  = idt_entry->selector;
  127.   i_e->type      = idt_entry->type;
  128.   i_e->offset_hi = idt_entry->offset_hi;
  129. }
  130. /* ---------------------------------------------------------------------- */
  131. static void
  132. analyze_eip (void)
  133. { if (eip <= segment_stp_addr && eip >= segment_str_addr)
  134.   {
  135.     eip -= segment_str_addr;
  136.     evaluation_data[eip / segment_len].hits_count++;
  137.   }
  138.   total_hits_count++;
  139. }
  140. /* ---------------------------------------------------------------------- */
  141. static void
  142. emulate_rm_isr_08 (void)
  143. {
  144.   asm("cli");
  145.   asm("push %eax");
  146.   asm("push %edx");
  147.   asm("push %ds");
  148.   asm("push $0x48");
  149.   asm("pop  %ds");
  150.   dos_clock_tick += pulses_per_mili;
  151.   asm("mov  $0x20,%al");
  152.   asm("out  %al,$0x20");
  153.   asm("pop  %ds");
  154.   asm("pop  %edx");
  155.   asm("pop  %eax");
  156. }
  157. /* ---------------------------------------------------------------------- */
  158. static void
  159. emulate_pm_isr_08 (void)
  160. {
  161.   asm("cli");
  162.   asm("push %eax");
  163.   asm("push %ebx");
  164.   asm("push %ecx");
  165.   asm("push %edx");
  166.   asm("push %ds");
  167.   asm("push $0x48");
  168.   asm("pop  %ds");
  169.  
  170.   dos_clock_tick += pulses_per_mili;
  171.   if (dos_clock_tick < dos_clock_limit)
  172.   {
  173.     asm("mov  $0x20,%al");
  174.     asm("out  %al,$0x20");
  175.   } else
  176.   {
  177.     asm("movl %ebp,_ebp");
  178.     asm("movl %esp,_esp");
  179.  
  180.     old_isr_regs.x.cs = old_rm_isr.rm_segment;
  181.     old_isr_regs.x.ip = old_rm_isr.rm_offset;
  182.     old_isr_regs.x.ss = old_isr_regs.x.sp = 0;
  183.     regs.x.ax = 0x302;
  184.     regs.h.bh = 0;
  185.     regs.x.cx = 0;
  186.     regs.x.di = (unsigned long)(&old_isr_regs);
  187.     int86 (0x31, ®s, ®s);
  188.     asm("cli");
  189.  
  190.     asm("movl _esp,%esp");
  191.     asm("movl _ebp,%ebp");
  192.  
  193.     dos_clock_tick -= dos_clock_limit;
  194.   }
  195.   asm("pop  %ds");
  196.   asm("pop  %edx");
  197.   asm("pop  %ecx");
  198.   asm("pop  %ebx");
  199.   asm("pop  %eax");
  200.   asm("leave");
  201.   asm("iret");
  202. }
  203. /* ---------------------------------------------------------------------- */
  204. static void
  205. my_pm_isr_08 (void)
  206. {
  207.   asm("push %eax");
  208.   asm("push %ecx");
  209.   asm("push %edx");
  210.   asm("push %ds");
  211.   asm("push $0x48");
  212.   asm("pop  %ds");
  213.  
  214.   if (ok_to_run)
  215.   {
  216.     asm("movl %ebp,%eax");
  217.     asm("add  $0x04,%eax");
  218.     asm("movl (%eax),%edx");
  219.     asm("movl %edx,_eip");
  220.  
  221.     analyze_eip ();
  222.   }
  223.  
  224.   asm("pop  %ds");
  225.   asm("pop  %edx");
  226.   asm("pop  %ecx");
  227.   asm("pop  %eax");
  228.   asm("leave");
  229.  
  230.   asm("push %eax");         /* <=> db 50h  */
  231.   asm("push %eax");         /* <=> db 50h  */
  232.   asm("push %eax");         /* <=> db 50h  */
  233.   asm("push %eax");         /* <=> db 50h  */
  234.   asm("push %eax");         /* <=> db 50h  */
  235.   asm("push %eax");         /* <=> db 50h  */
  236.   asm("push %eax");         /* <=> db 50h  */
  237. }
  238. /* ---------------------------------------------------------------------- */
  239. int
  240. set_timer ()
  241. {
  242.   word32 old_selector, old_offset, jump_pos;
  243.  
  244.   if (_go32_info_block.run_mode == _GO32_RUN_MODE_DPMI)
  245.     return (0);
  246.   if (!timer_is_set)
  247.   {
  248.     pm_si.pm_offset = (int) my_pm_isr_08;
  249.     pm_si.pm_selector = _go32_my_cs();
  250.  
  251.     asm("cli");
  252.     get_idt_entry (8, &pm_old_idt_entry);
  253.     asm("sti");
  254.  
  255.     jump_pos = (int) my_pm_isr_08 + 0x2b;
  256.     old_offset  = ((unsigned long)pm_old_idt_entry.offset_hi << 16) |
  257.            (unsigned long)pm_old_idt_entry.offset_lo;
  258.     old_selector = (unsigned long)pm_old_idt_entry.selector;
  259.     if (old_offset)
  260.     {
  261.       write_child (jump_pos + 4, &old_selector, 2);
  262.       write_child (jump_pos    , &old_offset, 4);
  263.       old_offset   = 0xea;     /* Opcode for intersegment jump */
  264.       write_child (jump_pos - 1, &old_offset, 1);
  265.  
  266.       timer_is_set = 1;
  267.     }
  268.     else
  269.     {
  270.       int ret;
  271.  
  272.       emu_rm_si.pm_offset = (int) emulate_rm_isr_08;
  273.       emu_pm_si.pm_offset = (int) emulate_pm_isr_08;
  274.       emu_pm_si.pm_selector = _go32_my_cs();
  275.  
  276.       ret = _go32_dpmi_allocate_real_mode_callback_iret(
  277.         &emu_rm_si, &emu_rm_regs);
  278.       if (ret)
  279.     return 0;
  280.  
  281.       disable();
  282.  
  283.       _go32_dpmi_get_real_mode_interrupt_vector(8, &old_rm_isr);
  284.       _go32_dpmi_set_real_mode_interrupt_vector(8, &emu_rm_si);
  285.       _go32_dpmi_set_protected_mode_interrupt_vector(8, &emu_pm_si);
  286.  
  287.       outportb (command_reg, ch_0_seq);
  288.       outportb (timer_channel, pulses_per_mili & 0xff);
  289.       outportb (timer_channel, pulses_per_mili >> 8);
  290.  
  291.       enable();
  292.  
  293.       old_offset  = (unsigned long) emulate_pm_isr_08;
  294.       old_selector = _go32_my_cs ();
  295.       write_child (jump_pos + 4, &old_selector, 2);
  296.       write_child (jump_pos    , &old_offset, 4);
  297.       old_offset   = 0xea;     /* Opcode for jump */
  298.       write_child (jump_pos - 1, &old_offset, 1);
  299.  
  300.       timer_is_set = 2;
  301.     }
  302.  
  303.     asm("cli");
  304.     _go32_dpmi_set_protected_mode_interrupt_vector(8, &pm_si);
  305.     asm("sti");
  306.  
  307.     return 1;
  308.   } 
  309.   return 0;
  310. }
  311. /* ---------------------------------------------------------------------- */
  312. void
  313. reset_timer ()
  314. {
  315.   if (timer_is_set)
  316.   {
  317.     asm("cli");
  318.     set_idt_entry (8, &pm_old_idt_entry);
  319.     asm("sti");
  320.  
  321.     if (timer_is_set == 2)
  322.     {
  323.       disable();
  324.  
  325.       outportb (command_reg, ch_0_seq);
  326.       outportb (timer_channel, 0);
  327.       outportb (timer_channel, 0);
  328.  
  329.       _go32_dpmi_set_real_mode_interrupt_vector(8, &old_rm_isr);
  330.       _go32_dpmi_free_real_mode_callback (&emu_rm_si);
  331.  
  332.       enable();
  333.     }
  334.  
  335.     timer_is_set = 0;
  336.   }
  337. }
  338. /* ---------------------------------------------------------------------- */
  339. void
  340. start_evaluate ()
  341. {
  342.   if (timer_is_set)
  343.   {
  344.     evaluation_is_running = 1;
  345.     ok_to_run = 1;
  346.   }
  347. }
  348. /* ---------------------------------------------------------------------- */
  349. void
  350. stop_evaluate ()
  351. {
  352.   ok_to_run = 0;
  353.   evaluation_is_running = 0;
  354. }
  355. /* ---------------------------------------------------------------------- */
  356. void
  357. init_eval_data (word32 start_addr, word32 stop_addr)
  358. {
  359.   int i;
  360.   word32 real_str = start_addr, real_stp = stop_addr;
  361.  
  362.   if ((!valid_addr (real_str, 1)) || (!valid_addr(real_stp - 1, 1)))
  363.   { real_str = areas[A_text].first_addr;
  364.     real_stp = areas[A_text].last_addr;
  365.   }
  366.   segment_str_addr = real_str;
  367.   segment_stp_addr = real_stp;
  368.   segment_len      = (real_stp - real_str) / EVAL_SEGMENTS;
  369.   if (segment_len <= 0)
  370.     segment_len = 1;
  371.  
  372.   for (i = 0; i < EVAL_SEGMENTS; i++)
  373.   {
  374.     evaluation_data[i].start_addr = i * segment_len + real_str;
  375.     evaluation_data[i].stop_addr =  (i + 1) * segment_len - 1 + real_str;
  376.     evaluation_data[i].hits_count = 0;
  377.   }
  378.   total_hits_count = 0;
  379. }
  380. /* ---------------------------------------------------------------------- */
  381.